package com.yctan.single;
// Handler線程

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;

/**
 * 处理器
 * @author 谭永超
 */
public class TCPHandler implements Runnable {

    private final SelectionKey sk;
    private final SocketChannel sc;

    int state;

    public TCPHandler(SelectionKey sk, SocketChannel sc) {
        this.sk = sk;
        this.sc = sc;
        // 初始状态设置为读
        state = 0;
    }

    @Override
    public void run() {
        try {
            if (state == 0) {
                // 读取网络数据
                read();
            }
            else {
                // 发送网络数据
                send();
            }
        } catch (IOException e) {
            System.out.println(Thread.currentThread().getName()+"[Warning!] A client has been closed.");
            closeChannel();
        }
    }

    private void closeChannel() {
        try {
            sk.cancel();
            sc.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    private synchronized void read() throws IOException {
        System.out.println(Thread.currentThread().getName()+"---------------开始读取-------------------");
        System.out.println(Thread.currentThread().getName()+sc.socket().getRemoteSocketAddress().toString()+"连接");
        // non-blocking下不可用Readers，因為Readers不支援non-blocking
        byte[] arr = new byte[1024];
        ByteBuffer buf = ByteBuffer.wrap(arr);
        // 读取字符串
        int numBytes = sc.read(buf);
        if(numBytes == -1)
        {
            System.out.println(Thread.currentThread().getName()+"[警告！] 一个客户端已关闭。");
            closeChannel();
            return;
        }
        // 将读取字符串byte内容转为字符串类型
        String str = new String(arr);
        if ((str != null) && !str.equals(" ")) {
            System.out.println(Thread.currentThread().getName()+str);
            // 处理逻辑
            process(str);
            // 改变状态
            state = 1;
            // 通過key改变通道的类型为写
            sk.interestOps(SelectionKey.OP_WRITE);
            // 使一个阻塞住的selector操作立即返回
            sk.selector().wakeup();
            System.out.println(Thread.currentThread().getName()+"---------------读取完成-------------------");
        }
    }

    private void send() throws IOException  {

        System.out.println(Thread.currentThread().getName()+"---------------开始写入-------------------");
        System.out.println(Thread.currentThread().getName()+sc.socket().getRemoteSocketAddress().toString()+"连接");
        String str = "HTTP/1.1 200 \r\n" +
                "Content-Length: 2 \r\n" +
                "Content-Type: application/json\r\n" +
                "\r\n" +
                "{}";
        // wrap自动把buf的position设置0，所以不需要再flip()
        ByteBuffer buf = ByteBuffer.wrap(str.getBytes());
        while (buf.hasRemaining()) {
            // 回传給client回應字符串，发送buf的position位置 到limit位置为止之间的內容
            sc.write(buf);
        }
        // 改变状态
        state = 0;
        // 通过key改变通道註冊的事件
        sk.interestOps(SelectionKey.OP_READ);
        // 使一个阻塞住的selector操作立即返回
        sk.selector().wakeup();
        System.out.println(Thread.currentThread().getName()+"---------------写入完成-------------------");
    }

    void process(String str) {
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
